package com.szcinda.controller;

import com.szcinda.repository.OperationLog;
import com.szcinda.repository.OperationLogRepository;
import com.szcinda.repository.User;
import com.szcinda.service.SnowFlakeFactory;
import com.szcinda.service.dto.user.UserService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * @author 黄任森
 * @title: OperationAspect
 * @projectName 星达
 * @date 2023/4/4
 * @description: 操作日志切面处理类
 */
@Aspect
@Component
public class OperationLogAspect {

    private final OperationLogRepository operationLogRepository;
    private final SnowFlakeFactory snowFlakeFactory;
    private final UserService userService;

    public OperationLogAspect(OperationLogRepository operationLogRepository, UserService userService) {
        this.operationLogRepository = operationLogRepository;
        this.userService = userService;
        this.snowFlakeFactory = SnowFlakeFactory.getInstance();
    }

    /**
     * 设置操作日志切入点   在注解的位置切入代码
     */
    @Pointcut("@annotation(com.szcinda.controller.OperationLogAnnotation)")
    public void opLogPointCut() {
    }

    @AfterReturning(returning
            /**
             * 记录操作日志
             * @param joinPoint 方法的执行点
             * @param result  方法返回值
             * @throws Throwable
             */ = "result", value = "opLogPointCut()")
    public void saveOperLog(JoinPoint joinPoint, Object result) throws Throwable {
        // 获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        // 从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        try {
            //将返回值转换成map集合
            OperationLog operationLog = new OperationLog();
            // 从切面织入点处通过反射机制获取织入点处的方法
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            //获取切入点所在的方法
            Method method = signature.getMethod();
            //获取操作
            OperationLogAnnotation annotation = method.getAnnotation(OperationLogAnnotation.class);
            if (annotation != null) {
                // 操作内容
                operationLog.setContent(annotation.operDesc());
                // 操作模块
                operationLog.setTargetId(annotation.operModel());
                // 操作人
                operationLog.setUserName(request.getHeader("userName"));
                //操作时间
                operationLog.setCreateTime(LocalDateTime.now());
                operationLog.setTargetId("");
                if (StringUtils.hasText(request.getHeader("userId"))) {
                    User user = userService.findUserById(request.getHeader("userId"));
                    operationLog.setUserName(user.getAccount());
                }
                operationLog.setUserId(request.getHeader("userId"));
                operationLog.setId(snowFlakeFactory.nextId("LG"));
                if(StringUtils.isEmpty(operationLog.getUserId())){
                    return;
                }
                //保存日志
                operationLogRepository.save(operationLog);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
